IoTシステムでユースケースの追加によりDynamoDBの再設計が必要となった話
こんにちは。CX事業本部の若槻です。
今回はAWSのマネージドサービス(IoT Core、Lambda、DynamoDBなど)を利用したIoTシステムの導入にて、追加で発生したビジネス上のユースケースに既存のDynamoDBのテーブル設計では対応ができなくなったため再設計が必要となった、というケースがあったためご紹介します。
どんなシステムか
戸建て住宅の設備(例:玄関の扉)にIoTデバイスを設置し、設備が最後に利用された時刻(例:扉が最後に開閉された時刻)をDynamoDBに記録するサービスを提供するシステムです。
DynamoDBのプロパティは以下のようになります。
placeId
(住宅の識別値)placeName
(住宅の名称)deviceId
(IoTデバイスの識別値)lastOpenCloseAt
(最終開閉時刻)
DynamoDBのテーブルには以下のようにデータが格納されます。
placeId | placeName | deviceId | lastOpenCloseAt |
---|---|---|---|
place001 | 住宅A | device001 | 1574599548 |
place002 | 住宅B | device002 | 1574600014 |
place003 | 住宅C | device003 | 1574519724 |
キー・インデックスの指定は以下のようになります。ソートキーの指定はないため、プライマリキーはplaceId
のみとなります。
- パーティションキー:
placeId
- ソートキー:なし
DynamoDBでデータが更新されるまでの一連の流れは以下のようになります。
- IoTデバイスが玄関扉の開閉を検知する
- IoTデバイスからAWSへ開閉時刻が送信される
- DynamoDBのテーブルに対してパーティションキーである
placeId
をもとに更新対象のデータの検索が行われる - 更新対象のデータの
lastOpenCloseAt
が更新される
追加のユースケースと、それによりDynamoDB観点で何が対応できなくなるのか
さて、ここで追加のユースケースとして「表口と裏口の2つの玄関を持つ住宅」に対しても同システムで対応ができるかどうか検討することとなりました。 その場合は表口と裏口のそれぞれの玄関にIoTデバイスを設置し、それぞれの最終開閉時刻を記録する必要があります。
当初の想定では、システムの対象となる住宅は1つの玄関(=1つのIoTデバイス)を持つケースのみであり、placeId
とdeviceId
は1対1の関係であったため、問題なく対応できていました。
しかし、追加のユースケースでは1つの住宅に2つの玄関があるため、placeId
とdeviceId
は1対2の関係となります。この場合はどうなるでしょうか?結論から言いますと、既存のテーブル設計では対応は不可となります。
[理想]としては以下のように住宅C
の表口(device003
)と裏口(device004
)の両方のIoTデバイスのデータが既存のテーブルに登録できると良いでしょう。
placeId | placeName | deviceId | lastOpenCloseAt |
---|---|---|---|
place001 | 住宅A | device001 | 1574599548 |
place002 | 住宅B | device002 | 1574600014 |
place003 | 住宅C | device003 | 1574519724 |
place003 | 住宅C | device004 | 1574607363 |
しかし[実際]には以下のように既に登録されているdevice003
のデータにdevice004
のデータが上書きされる動作となります。
placeId | placeName | deviceId | lastOpenCloseAt |
---|---|---|---|
place001 | 住宅A | device001 | 1574599548 |
place002 | 住宅B | device002 | 1574600014 |
place003 | 住宅C | device004 | 1574607363 |
これは、プライマリキーであるplaceId
は同じテーブル内で値がユニークである必要があるため、同じデータとして扱われてしまったためです。
よってテーブル設計においてキー・インデックスの指定を以下のように再設計する必要があります。
- パーティションキー:
placeId
- ソートキー:
deviceId
ソートキーにdeviceId
を指定することにより、placeId
+ deviceId
から成るプライマリキーが追加のユースケースにおいてもユニークな値となるため、既存の設計では対応ができなかったdevice003
とdevice004
の両方のデータの登録が可能となります。
おわりに
すでにDynamoDBの利用経験がある方にとっては初級レベルの内容のエントリだと思いますが、わたしは業務でAWSに触れるのが初めてであったため既存のテーブル設計で何がだめなのか理解をするのに時間を要しました。
今回のケースを通して、データベースとして概念設計の時点でユースケースの洗い出しを入念に行うことが、拡張性のあるDynamoDBのシステムを作る上で大切であることを実感しました。
参考
- DynamoDBのテーブル設計をするとき、自分に問いかけていること | 或る阿呆の記
- DynamoDBを使い始めて気をつけていること。DynamoDBをLambdaで使いたい | 或る阿呆の記
- DynamoDBデータモデリング虎の巻:第弐巻 〜考え方編〜 | misc.tech.notes
以上